魔法陣言語parserのcode reading
背景takker.icon
魔法陣言語はinajob.github.ioで試せるが、clientで実行する必要がある ということで、parser部分だけ抜き出して再実装しようと試みた
init()でSVGとラスタイメージを生成している
(function(){/*...*/}).toString()という黒魔術っぽいコードがある
class
SVGレンダラー
ラスタレンダラー
機械的にmordernizeできるか試してみたけど無理だったtakker.icon
MCLがお目当てのparserっぽいtakker.icon
じゃあなんでentry pointでもパーサーを使っているんだろう?
どこだろう? 黒魔術っぽいところは単に文字列を作ってるだけですね。inajob.icon
draw()のworker.onmessageのvar out = p.parse(sout);です(var p = new SimpleParser();)takker.icon
魔法陣言語をレンダー用の中間言語(文字列)としてWorkerとやり取りしているようで、受け取った文字列をレンダー言語の構造に変換するのがSimpleParserのようですね(おおむね改行区切りでリストにするだけですが)inajob.icon
WebWorkerのメッセージでArrayを渡せないんだっけ?(忘れた)
いけそうにみえるな
かつてはダメだったのかな・・?覚えてないです
データコピーの都合がつかなかったのかな?takker.icon
MCLをcode readingする
$で始まるものは定義済み終端記号
$DECIMAL:数値
$JS_STRING:JSの文字列
[],"",<>で囲まれた文字列が終端記号となる
<>は中身を正規表現として解釈する
:の前で認識した記号は、その後と同名の関数(別途定義)で処理される
PROGRAMから解析を開始する
/[ \r\n]/は適宜無視される
code:js
this.parser = new Gin.Grammar({
Stmnt: /Cmp:cmp | ! ARG:push = Cmp:assign/, // 代入演算、即値 Cmp: / Expr (< Expr:gt | > Expr:lt | == Expr:eq | != Expr:neq)* /, // 比較演算 Expr: / Term (+ Term:add | - Term:sub)* /, // 加減演算 Term: / Fctr (* Fctr:mul | / Fctr:div | % Fctr:mod)* /, // 乗除演算 // 数字、変数、関数、文字列、括弧
Fctr: / $DECIMAL:fpush | Def | Call | $JS_STRING:push | ( Cmp:pushn ) /, Call: /(ARG:vpush|( Cmp)):callBegin (("(" ARGLIST{0,1} ")":prepareBlock (("{" PROGRAM "}"){0,1}):funcBody) {0,1}):funcCall/, // 関数定義
Def: /\\:defBegin ("(" ARGLIST{0,1} ")":prepareBlock "{" PROGRAM "}":funcBody):funcDef/, // プログラム全行
PROGRAM: /((LINE:line (<;>){0,1})*)/,
LINE: /Stmnt COMM/, //ブロック解析
COMM: /<(\/\/^\r\n*|)>/, //コメント ARGLIST: /Stmnt:arg (',' ARGLIST){0,1}/, // 引数リスト
},"PROGRAM", new Gin.Parser.RegExp(/ \r\n/)); 仕様書も参照したいが、リンク切れなのでコードから文法を推測するしかない
コードから関数定義(Def)の様子がわからない
\(a,b,c){ PROGRAM }と書くみたい?
関数名の定義はしないの?無名関数なのか?
Yes、変数に代入して使いますinajob.icon
あたったtakker.icon
それにFctrにDefが含まれているから、3+\(a,b,c){...}もvalidになってしまう
どう計算するんだろう
これは実行時エラーになりそうinajob.icon
単に文法エラーにしてないだけですね。了解ですtakker.icon
途中まで書いて挫折
上述した不可解な文法があり、具体的なコードのイメージがつかなかった
やっぱり作例か仕様書がないと、これ以上読み解けない
後で見えるところに置きますねinajob.icon
現時点だとMCE3の、ソースのpreludeが参考になるかも これか!ありがとうございますtakker.icon
変数宣言・代入に!をつけるのか
やりたくなかったけど、パーサー周りで試行錯誤して、よくわからなかったので妥協した記憶inajob.icon
歴史的経緯takker.icon
リンク切れ解消しました!
ありがとうございます!見れました!takker.icon
15:28:39 字句解析までできた
はやい!inajob.icon
2024-04-01 13:55:32 実行エンジン完成
テストはまだしてないので動くかどうかわからない
組み込み関数は未実装